iT邦幫忙

2024 iThome 鐵人賽

DAY 7
0
Modern Web

Laravel 那麼好用還需要自幹框架嗎系列 第 7

Day 07:Laravel 如何建立路由物件

  • 分享至 

  • xImage
  •  

昨天我們看到了 Laravel 如何引入 routes/web.php 等等檔案

今天我們來看看 Laravel 怎麼建立路徑。

一般來說,Laravel 框架宣告路徑有兩種方式

第一種是比較正式的宣告,使用 Controller 的名字和方法名稱

use App\Http\Controllers\UserController;
 
Route::get('/user', [UserController::class, 'index']);

這邊的 Route 全名為 Illuminate\Support\Facades\Route

class Route extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'router';
    }
}

如果只看這段程式,是無法往下繼續找實作的
必須要找註解內標記的

@see \Illuminate\Routing\Router

才能找到這段程式實際實作的位置。

Router 裡面實作 get() 的部分如下

/**
 * Register a new GET route with the router.
 *
 * @param  string  $uri
 * @param  array|string|callable|null  $action
 * @return \Illuminate\Routing\Route
 */
public function get($uri, $action = null)
{
	return $this->addRoute(['GET', 'HEAD'], $uri, $action);
}

如果我們定義了 GET 的路徑,Laravel 會幫我們加上一個 HEAD 的路徑。

根據 MDN Web Docs 的說明, HEAD 的用途如下

HTTP HEAD 方法請求返回與使用 HTTP GET 方法請求相同 URL 時將返回的標頭。例如,如果某個 URL 可能產生大文件下載,則 HEAD 請求可以讀取其 Content-Length 標頭以檢查文件大小,而無需實際下載文件。

這邊我們先不處理這一段,往下看 GET 建立的內容。

addRoute() 實作的內容如下

public function addRoute($methods, $uri, $action)
{
	return $this->routes->add($this->createRoute($methods, $uri, $action));
}

這邊的邏輯很簡單,就是透過 createRoute()  建立路由物件之後,將建立好的物件加入 $this->routes 裡面

createRoute() 實作如下:

protected function createRoute($methods, $uri, $action)
{
	// If the route is routing to a controller we will parse the route action into
	// an acceptable array format before registering it and creating this route
	// instance itself. We need to build the Closure that will call this out.
	if ($this->actionReferencesController($action)) {
		$action = $this->convertToControllerAction($action);
	}

	$route = $this->newRoute(
		$methods, $this->prefix($uri), $action
	);

	// If we have groups that need to be merged, we will merge them now after this
	// route has already been created and is ready to go. After we're done with
	// the merge we will be ready to return the route back out to the caller.
	if ($this->hasGroupStack()) {
		$this->mergeGroupAttributesIntoRoute($route);
	}

	$this->addWhereClausesToRoute($route);

	return $route;
}

又是一個註解比起實作內容要多的程式。相信各位讀者看到這邊應該已經有感覺,當遇到這種狀況時,就代表我們開始接觸到一些需要說明的核心邏輯,而且這些邏輯通常複雜到我們無法快速的透過程式碼理解其內容。

我們來看看第一段邏輯

// If the route is routing to a controller we will parse the route action into
// an acceptable array format before registering it and creating this route
// instance itself. We need to build the Closure that will call this out.
if ($this->actionReferencesController($action)) {
	$action = $this->convertToControllerAction($action);
}

這段會將前面輸入的內容,轉換成可用的陣列。

經過轉換之後,接著會建立一個新的 Route 物件

/**
 * Create a new Route object.
 *
 * @param  array|string  $methods
 * @param  string  $uri
 * @param  mixed  $action
 * @return \Illuminate\Routing\Route
 */
public function newRoute($methods, $uri, $action)
{
	return (new Route($methods, $uri, $action))
				->setRouter($this)
				->setContainer($this->container);
}

建立好了之後,就可以將新建立好的 Route 物件透過 $this->routes->add() 加入 $this->routes內。

這邊的 $this->routes 實作了 \Illuminate\Routing\RouteCollectionInterface,當我們查看誰實作這個介面時,可以發現只有 AbstractRouteCollection 實作該介面

abstract class AbstractRouteCollection implements Countable, IteratorAggregate, RouteCollectionInterface

至於繼承 AbstractRouteCollection 的,則是 Illuminate\Routing\RouteCollection 類別

class RouteCollection extends AbstractRouteCollection

到這邊,我們看了當我們撰寫

Route::get('/user', [UserController::class, 'index']);

這段程式時, Laravel 是怎麼處理這段內容,建立一個 Route 物件,並將其加入到 RouteCollection  裡面。


上一篇
Day 06:Laravel 如何引入路由檔案
下一篇
Day 08:Laravel 怎麼處理請求
系列文
Laravel 那麼好用還需要自幹框架嗎18
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言